package com.jxit0573.android.lib.util;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.widget.ImageView;

import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.jxit0573.android.lib.common.PicassoEngine;
import com.jxit0573.android.lib.impl.OnCompressListener;
import com.squareup.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import com.squareup.picasso.Target;
import com.zhihu.matisse.Matisse;
import com.zhihu.matisse.MimeType;
import com.zhihu.matisse.internal.entity.CaptureStrategy;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import top.zibin.luban.Luban;

/**
 * @author jia
 */
public class ImageUtils {

    private ImageUtils() {
    }

    public static void init(Context context, OkHttpClient client) {
        Picasso picasso = new Picasso.Builder(context)
                .downloader(new OkHttp3Downloader(client))
                .build();
        Picasso.setSingletonInstance(picasso);
    }

    public static void display(ImageView target, @Nullable String path, @DrawableRes int placeholderResId, @DrawableRes int errorResId) {
        if (target == null) {
            return;
        }
        RequestCreator creator;
        if (TextUtils.isEmpty(path)) {
            if (errorResId == 0) {
                return;
            } else {
                creator = Picasso.get().load(errorResId);
            }
        } else {
            creator = Picasso.get().load(path);
            if (placeholderResId != 0) {
                creator.placeholder(placeholderResId);
            }
            if (errorResId != 0) {
                creator.error(errorResId);
            }
        }
        creator.into(target);
    }

    public static void compress(final Context context, CompositeDisposable disposable, List<String> selected, final OnCompressListener listener) {
        disposable.add(Flowable.just(selected)
                .observeOn(Schedulers.io())
                .map(list -> Luban.with(context)
                        .load(list)
                        .filter(path -> !TextUtils.isEmpty(path) && !(path.toLowerCase().endsWith(".gif")))
                        .ignoreBy(100)
                        .setTargetDir(FileUtils.getAppDirFile(context, "/compress").getPath()).get())
                .doOnError(throwable -> {
                    if (listener != null) {
                        listener.onError();
                    }
                }).onErrorResumeNext(Flowable.empty())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(files -> {
                    if (listener != null) {
                        listener.onSuccess(files);
                    }
                }));
    }

    public static void download(String url, final String path) {
        Picasso.get().load(url).into(new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                if (bitmap != null) {
                    try {
                        File file = new File(path);
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                        FileOutputStream fos = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onBitmapFailed(Exception e, Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        });
    }

    public static void selector(Activity activity, int maxSelectable, int requestCode) {
        Matisse.from(activity)
                .choose(MimeType.ofImage())
                .showSingleMediaType(true)
                .countable(true)
                .maxSelectable(maxSelectable)
                .capture(true)
                .captureStrategy(new CaptureStrategy(true, activity.getPackageName() + ".fileprovider"))
                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .imageEngine(new PicassoEngine())
                .forResult(requestCode);
    }

    public static void selector(Fragment fragment, int maxSelectable, int requestCode) {
        Matisse.from(fragment)
                .choose(MimeType.ofImage())
                .showSingleMediaType(true)
                .countable(true)
                .maxSelectable(maxSelectable)
                .capture(true)
                .captureStrategy(new CaptureStrategy(true, fragment.getActivity().getPackageName() + ".fileprovider"))
                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .imageEngine(new PicassoEngine())
                .forResult(requestCode);
    }

    public static void selectorVideo(Activity activity, int maxSelectable, int requestCode) {
        Matisse.from(activity)
                .choose(MimeType.ofVideo())
                .showSingleMediaType(true)
                .countable(true)
                .maxSelectable(maxSelectable)
                .capture(true)
                .captureStrategy(new CaptureStrategy(true, activity.getPackageName() + ".fileprovider"))
                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .imageEngine(new PicassoEngine())
                .forResult(requestCode);
    }

    public static List<String> obtainResult(Intent data) {
        if (data == null) {
            return null;
        } else {
            return Matisse.obtainPathResult(data);
        }
    }
}
